package git.soulbgm.controller;

import git.soulbgm.pojo.MessageDto;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * RabbitMQ控制器
 *
 * @author SoulBGM
 * @date 2022/09/06 17:59
 */
@RestController
public class RabbitmqController {

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private AmqpAdmin amqpAdmin;

    @PostMapping("send")
    public String send(String routingKey, String message) {
        String uuid = UUID.randomUUID().toString();
        Date createTime = new Date();
        if ("manual".equals(routingKey)) {
            Map<String, Object> map = new HashMap<>(3);
            map.put("messageId", uuid);
            map.put("message", message);
            map.put("createTime", createTime);
            amqpTemplate.convertAndSend(routingKey, map);
        } else {
            MessageDto dto = new MessageDto();
            dto.setMessageId(uuid);
            dto.setMessage(message);
            dto.setCreateTime(createTime);
            amqpTemplate.convertAndSend(routingKey, dto);
        }
        return "success";
    }

    @PostMapping("sendExchange")
    public String sendExchange(String exchange, String routingKey, String message) {
        String uuid = UUID.randomUUID().toString();
        Date createTime = new Date();
        MessageDto dto = new MessageDto();
        dto.setMessageId(uuid);
        dto.setMessage(message);
        dto.setCreateTime(createTime);
        amqpTemplate.convertAndSend(exchange, routingKey, dto);
        return "success";
    }

    @PostMapping("sendDelay")
    public String sendDelay(String exchange, String routingKey, String message, Long delay) {
        String uuid = UUID.randomUUID().toString();
        Date createTime = new Date();
        MessageDto dto = new MessageDto();
        dto.setMessageId(uuid);
        dto.setMessage(message);
        dto.setCreateTime(createTime);

        /*
        // 创建延迟交换机
        String queueName = "exchangeQueueDelay";
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        CustomExchange customExchange = new CustomExchange(exchange, "x-delayed-message", true, false, args);
        amqpAdmin.declareExchange(customExchange);
        // 创建消费队列
        Queue queue = new Queue(queueName, true);
        amqpAdmin.declareQueue(queue);
        // 队列绑定交换机
        Binding binding = BindingBuilder.bind(queue).to(customExchange).with(routingKey).noargs();
        amqpAdmin.declareBinding(binding);
        */

        amqpTemplate.convertAndSend(exchange, routingKey, dto, m -> {
            m.getMessageProperties().setHeader("x-delay", delay + "");
            return m;
        });
        return "success";
    }

    @PostMapping("sendTransaction")
    public String sendTransaction(String exchange, String routingKey, String message) {
        String uuid = UUID.randomUUID().toString();
        Date createTime = new Date();
        MessageDto dto = new MessageDto();
        dto.setMessageId(uuid);
        dto.setMessage(message);
        dto.setCreateTime(createTime);

        //确保消息发送失败后可以重新返回到队列中
        //需要配置 publisher-returns: true
        rabbitTemplate.setMandatory(true);
        //消费者确认收到消息后，手动ack回执回调处理
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.printf("生产者已经收到确认, ack=%s, cause=%s\n", ack, cause);
            } else {
                System.out.printf("消息发送异常, ack=%s, cause=%s\n", ack, cause);
            }
        });
        //消息投递到队列失败回调处理
        rabbitTemplate.setReturnCallback((message1, replyCode, replyText, exchange1, routingKey1) -> {
            System.out.printf("returnedMessage ===> replyCode=%s ,replyText=%s ,exchange=%s ,routingKey=%s\n",
                    replyCode, replyText, exchange1, routingKey1);
        });
        rabbitTemplate.convertSendAndReceive(exchange, routingKey, dto);
        return "success";
    }

    @PostMapping("createQueue")
    public String createQueue(String queue) {
        return amqpAdmin.declareQueue(new Queue(queue));
    }


}
